//package com.example.redisSimple.redisson;
//
//import io.netty.util.concurrent.Future;
//import io.netty.util.concurrent.FutureListener;
//import org.redisson.RedissonLock;
//import org.redisson.RedissonLockEntry;
//import org.redisson.api.RFuture;
//import org.redisson.client.codec.LongCodec;
//import org.redisson.client.protocol.RedisCommands;
//import org.redisson.client.protocol.RedisStrictCommand;
//import org.redisson.command.CommandExecutor;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//import org.springframework.util.IdGenerator;
//import org.springframework.util.JdkIdGenerator;
//
//import java.util.Collections;
//import java.util.List;
//import java.util.concurrent.ExecutionException;
//import java.util.concurrent.TimeUnit;
//
//@Service
//public class RedissonUtil {
//
//
//    @Autowired
//    private CommandExecutor commandExecutor;
//
//    /**
//     * 加锁
//     */
//    public void lock (long leaseTime, TimeUnit unit) throws ExecutionException, InterruptedException {
//
//        // 获取当前线程id
//        long threadId = Thread.currentThread().getId();
//        // 尝试获取锁
//        Long ttl = tryAcquire(leaseTime, unit, threadId).get();
//        // 如果ttl为空，则证明获取成功
//        if (ttl == null) {
//            return;
//        }
//
//        // 如果获取锁失败，则订阅到对应这个锁的channel
//        RFuture<RedissonLockEntry> future = subscribe(threadId);
//        commandExecutor.syncSubscription(future);
//
//        try {
//            while (true) {
//                // 再次尝试获取锁
//                ttl = tryAcquire(leaseTime,unit,threadId).get();
//                // ttl为空，说明成功获取锁，返回
//                if (ttl == null) {
//                    break;
//                }
//                // 如果ttl大于0 则等待ttl时间后继续尝试获取锁
//                if (ttl >= 0) {
//                    getEntity(threadId).getLatch().tryAcquire(ttl,TimeUnit.MILLISECONDS);
//                } else {
//                    getEntity(threadId).getLatch().acquire();
//                }
//            }
//        } finally {
//            // 取消对channel的订阅
//            unsubscribe(future,threadId);
//        }
//    }
//
//
//    /**
//     * 尝试获取锁
//     * 1. 首先判断是否有过期时间，如果有就尝试获取锁
//     *
//     * @param leaseTime
//     * @param unit
//     * @param threadId
//     * @return
//     */
//    private <T> RFuture<Long>  tryAcquire(long leaseTime, TimeUnit unit, long threadId) {
//
//        // 如果带有过期时间，则按照普通方式获取锁
//        if (leaseTime != -1) {
//            return tryLockInnerAsync(leaseTime,unit,threadId, RedisCommands.EVAL_LONG);
//        }
//
//        // 先按照30秒的过期时间来执行获取锁的方法
//        RFuture<Long> ttlRemainingFuture = tryLockInnerAsync(
//                commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(),
//                TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
//
//        // 如果还持有这个锁，则开启定时任务不断刷新该锁的过期时间
//        ttlRemainingFuture.addListener(new FutureListener<Long>() {
//               @Override
//               public void operationComplete(Future<Long> future) throws Exception {
//                    if (!future.isSuccess()) {
//                        return;
//                    }
//                    Long ttlRemaining = future.getNow();
//                    // lock acquired
//                   if (ttlRemaining == null) {
//                       scheduleExpirationRenewal(commandExecutor.getConnectionManager().getCfg().getLockWatchdogTimeout(),
//                               TimeUnit.MILLISECONDS, threadId, RedisCommands.EVAL_LONG);
//                   }
//               }
//           }
//        );
//        return ttlRemainingFuture;
//    }
//
//
//
//    private static final String REDIS_LUA_LOCK =
//            "if (redis.call('exists',KEYS[1]) == 0) then " +
//                    " redis.call('hset',KEYS[1],ARGV[2],1);\" +\n" +
//                    " redis.call('pexpire',KEYS[1],ARGV[1]);\" +\n" +
//                    " return nil;\" +\n" +
//                    " end; ";
//
//    private static final String REDIS_LUA =
//            // 如果锁不存在，通过hset设置它的值，并设置过期时间
//            "if (redis.call('exists',KEYS[1]) == 0) then" +
//            "redis.call('hset',KEYS[1],ARGV[2],1);" +
//            "redis.call('pexpire',KEYS[1],ARGV[1]);" +
//            "return nil;" +
//            "end; " +
//            // 如果锁已存在，并且锁的是当前线程，则通过hincrby给数值递增1
//            "if (redis.call('hexists',KEYS[1],ARGV[2]) == 1) then " +
//            "redis.call('hincrby',KEYS[1],ARGV[2],2);" +
//            "redis.call('pexpire',KEYS[1],ARGV[1]);" +
//            "return nil;" +
//            "end;" +
//            // 如果锁以及存在，但并非本线程，则返回过期时间ttl
//            "return redis.call('pttl',KEYS[1]);";
//
//    private static final String lockName = "lock1";
//
//    <T> RFuture<T> scheduleExpirationRenewal(long leaseTime, TimeUnit unit,
//                                             long threadId, RedisStrictCommand<Long> command) {
//        // 过期时间
//        long internalLockLeaseTime = unit.toMillis(leaseTime);
//        List<Object> singletonList = Collections.<Object>singletonList(lockName);
//        return commandExecutor.evalWriteAsync(lockName, LongCodec.INSTANCE,command,REDIS_LUA_LOCK,singletonList,internalLockLeaseTime, getLockName(threadId));
//
//    }
//
//    <T> RFuture<T> tryLockInnerAsync(long leaseTime, TimeUnit unit,
//                                     long threadId, RedisStrictCommand<Long> command) {
//
//        // 过期时间
//        long internalLockLeaseTime = unit.toMillis(leaseTime);
//        List<Object> singletonList = Collections.<Object>singletonList(lockName);
//        return commandExecutor.evalWriteAsync(lockName, LongCodec.INSTANCE,command,REDIS_LUA,singletonList,internalLockLeaseTime, getLockName(threadId));
//
//    }
//
//    private String getLockName(long threadId) {
//        IdGenerator idGenerator = new JdkIdGenerator();
//        return idGenerator.generateId() + ":" + threadId;
//    }
//
//
//}
